﻿using Microsoft.Xna.Framework;
using System;

namespace TowerDefence.LanguageExtensions
{
    public static class Extensions
    {
        public static Rectangle copy(this Rectangle _r)
        {
            return new Rectangle(_r.X, _r.Y, _r.Width, _r.Height);
        }

        /// <summary>
        /// Gets the angle of a Vector2
        /// </summary>
        /// <param name="_vector">The vector</param>
        /// <returns>The angle in radians, compensating for SpriteBatch weirdness</returns>
        public static float GetSpriteBatchAngle(this Vector2 _vector)
        {
            float angle = (float)Math.Atan2((double)_vector.Y, (double)_vector.X);
            angle += MathHelper.PiOver2; // hax for spritebatch being weird
            return angle;
        }

		/// <summary>
		/// Rotates a vector around a specified origin by the specified angle.
		/// </summary>
		/// <param name="vector">
		/// Vector to rotate.
		/// </param>
		/// <param name="origin">
		/// Origin from which to rotate around.
		/// </param>
		/// <param name="angle">
		/// Magnitude of rotation in radians.
		/// </param>
		/// <returns>
		/// Rotated vector
		/// </returns>
		public static Vector2 RotateByAngle(this Vector2 vector, float angle, ref Vector2 origin)
		{
			// Precompute common subexpressions.
			float cosTheta = (float)Math.Cos(angle);
			float sinTheta = (float)Math.Sin(angle);
			float deltaX = vector.X - origin.X;
			float deltaY = vector.Y - origin.Y;

			// Set up the return vector. Return the parameter since it is a struct, and
			// has been cloned anyway.
			vector.X = (deltaX * cosTheta) - (deltaY * sinTheta) + origin.X;
			vector.Y = (deltaY * cosTheta) + (deltaX * sinTheta) + origin.Y;
			return vector;
		}


		/// <summary>
		/// Projects a virtual line from the supplied vector, with length and angle supplied, and
		/// returns the Vector2 location of the end point of the line.
		/// </summary>
		/// <param name="vector">
		/// The point from which the line is projected.
		/// </param>
		/// <param name="length">
		/// Length of the line to be projected.
		/// </param>
		/// <param name="angle">
		/// Angle the line makes with the X-axis. Care should be taken here, since the function
		/// is built for game screen coordinates, which are upside down compared to normal
		/// cartesian coordinates. This has the net effect that a positive angle indicates a
		/// counter-clockwise rotation from the x-axis, and a negative angle indicates a clockwise
		/// rotation. Negative is correct for all cases so the angle is inverted within the function.
		/// </param>
		/// <returns>
		/// Point on the end of the line.
		/// </returns>
		public static Vector2 ProjectLine(this Vector2 vector, float length, float angle)
		{
			// IF length = 0, it isn't a  projection. =D
			if (length == 0.0f)
			{
				return vector;
			}
			// ELSE project the line from the origin.
			else
			{
				// Use the parametric circle equation to project the line as if it was a radius.
				vector.X = vector.X + (length * (float)Math.Cos(-angle));
				vector.Y = vector.Y + (length * (float)Math.Sin(-angle));
				return vector;
			}
			// ENDIF
		}

    }
}
